﻿using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace LDM.Framework.Validation;

/// <summary>
/// 验证过滤器
/// </summary>
public class ValidationFilter : IAsyncActionFilter
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="context"></param>
    /// <param name="next"></param>
    /// <returns></returns>
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!(context.ActionDescriptor is ControllerActionDescriptor))
        {
            await next();
            return;
        }

        Validate(context.ModelState);
        await next();
    }

    /// <summary>
    /// 模型验证，如果有错误，则抛出 <see cref="ValidationException"/> 异常
    /// </summary>
    /// <param name="modelState"></param>
    /// <exception cref="ValidationException"></exception>
    private void Validate(ModelStateDictionary modelState)
    {
        var errors = new List<ValidationResult>();

        AddErrors(errors, modelState);

        if (!errors.Any())
        {
            return;
        }

        throw new ValidationException(string.Join("|", errors));
    }

    /// <summary>
    /// 添加模型验证错误信息到列表
    /// </summary>
    /// <param name="errors"></param>
    /// <param name="modelState"></param>
    private void AddErrors(List<ValidationResult> errors, ModelStateDictionary modelState)
    {
        if (modelState.IsValid)
        {
            return;
        }

        foreach (var state in modelState)
        {
            foreach (var error in state.Value.Errors)
            {
                errors.Add(new ValidationResult(error.ErrorMessage, new[] { state.Key }));
            }
        }
    }
}
